package com.action.gulimall.cart.service.impl;

import com.action.common.constant.CartConstant;
import com.action.common.utils.R;
import com.action.gulimall.cart.feign.ProductFeignService;
import com.action.gulimall.cart.interceptor.SetCookiesInterceptor;
import com.action.gulimall.cart.service.CartService;
import com.action.gulimall.cart.to.UserInfoTo;
import com.action.gulimall.cart.vo.CartItemVo;
import com.action.gulimall.cart.vo.CartVo;
import com.action.gulimall.cart.vo.SkuInfoVo;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.stream.Collectors;

/**
 * @author sl shilun217@qq.com
 * @Deacription TODO
 * @date 2021/06/29/14:16
 **/
@Service
public class CartServiceImpl implements CartService {
    @Autowired
    StringRedisTemplate stringRedisTemplate;

    @Autowired
    ProductFeignService productFeignService;

    @Override
    public void addCartItem(Long skuId, Integer num) throws ExecutionException, InterruptedException {
        BoundHashOperations<String, Object, Object> cartOps = getCartOps();
        String cartItemStr = (String)cartOps.get(skuId.toString());
        if(cartItemStr!=null){
            //修改购物项 的数量
            CartItemVo cartItemVo = JSON.parseObject(cartItemStr, CartItemVo.class);
            cartItemVo.setCount(cartItemVo.getCount()+num);
            cartOps.put(skuId.toString(), JSON.toJSONString(cartItemVo));
        }else{
            //新增购物项
            CartItemVo cartItemVo = new CartItemVo();
            //远程查询当前要添加商品的信息
            CompletableFuture<Void> skuInfoFuture = CompletableFuture.runAsync(() -> {
                R r = productFeignService.getSkuInfo(skuId);
                SkuInfoVo skuInfoVo = r.getData("skuInfo",new TypeReference<SkuInfoVo>() {}).get();
                cartItemVo.setSkuId(skuId);
                cartItemVo.setTitle(skuInfoVo.getSkuTitle());
                cartItemVo.setImage(skuInfoVo.getSkuDefaultImg());
                cartItemVo.setPrice(skuInfoVo.getPrice());
                cartItemVo.setCount(num);
            });
            //远程查询skuAttrValues组合信息
            CompletableFuture<Void> skuAttrValuesFuture = CompletableFuture.runAsync(() -> {
                R r = productFeignService.getSkuAttrValues(skuId);
                List<String>  skuAttrValues = r.getData(new TypeReference<List<String>>() {
                }).get();
                cartItemVo.setSkuAttrValues(skuAttrValues);
            });
            CompletableFuture.allOf(skuInfoFuture,skuAttrValuesFuture).get();
            cartOps.put(skuId.toString(), JSON.toJSONString(cartItemVo));
        }
    }

    @Override
    public CartItemVo getCartItem(Long skuId) {
        //拿到要操作的购物车信息
        BoundHashOperations<String, Object, Object> cartOps = getCartOps();
        String redisValue = (String) cartOps.get(skuId.toString());
        if(!StringUtils.isEmpty(redisValue)){
            CartItemVo cartItemVo = JSON.parseObject(redisValue, CartItemVo.class);
            return cartItemVo;
        }
        return null;
    }


    @Override
    public CartVo getCart() {
        CartVo cartVo = new CartVo();
        UserInfoTo userInfoTo = SetCookiesInterceptor.threadLocal.get();
        if(!userInfoTo.getTempUser()){
            //登录 购物车合并临时购物车 并删除临时购物车 返回购物车
            String cartKey = CartConstant.CART_IN_REDIS_PREFIX+userInfoTo.getUserId();
            String tempCartKey = CartConstant.CART_IN_REDIS_PREFIX+userInfoTo.getUserKey();
            List<CartItemVo> tempCartItems = getAllCartItems(tempCartKey);
            List<CartItemVo> cartItems = getAllCartItems(cartKey);
            if(!CollectionUtils.isEmpty(tempCartItems)){
                //将临时购物车转移到正式购物车
                switchTempCartToRealCart(cartKey, tempCartKey, tempCartItems, cartItems);
                //删除临时购物车
                cleanCart(tempCartKey);
            }
            cartVo.setItems(cartItems);
        }else{
            // 未登录 返回临时购物车
            String cartKey = CartConstant.CART_IN_REDIS_PREFIX+userInfoTo.getUserKey();
            List<CartItemVo> allCartItems = getAllCartItems(cartKey);
            cartVo.setItems(allCartItems);
        }
        // TODO 获取满减和折扣并加入计算总价
        return cartVo;
    }

    @Override
    public void changeCartItemCount(Long skuId, Integer num) {
        BoundHashOperations<String, Object, Object> cartOps = getCartOps();
        String cartItemStr = (String)cartOps.get(skuId.toString());
        if(cartItemStr!=null) {
            //修改购物项 的数量
            CartItemVo cartItemVo = JSON.parseObject(cartItemStr, CartItemVo.class);
            cartItemVo.setCount(num);
            cartOps.put(skuId.toString(), JSON.toJSONString(cartItemVo));
        }
    }

    @Override
    public void deleteCartItem(Long skuId) {
        BoundHashOperations<String, Object, Object> cartOps = getCartOps();
        cartOps.delete(skuId.toString());
    }

    @Override
    public void changeCartItemCheck(Long skuId, Integer checked) {
        BoundHashOperations<String, Object, Object> cartOps = getCartOps();
        String cartItemStr = (String)cartOps.get(skuId.toString());
        if(cartItemStr!=null) {
            //修改购物项 的数量
            CartItemVo cartItemVo = JSON.parseObject(cartItemStr, CartItemVo.class);
            cartItemVo.setCheck(checked == 1?true:false);
            cartOps.put(skuId.toString(), JSON.toJSONString(cartItemVo));
        }
    }

    @Override
    public Long cartNum() {
        UserInfoTo userInfoTo = SetCookiesInterceptor.threadLocal.get();
        if(!userInfoTo.getTempUser()) {
            String cartKey = CartConstant.CART_IN_REDIS_PREFIX + userInfoTo.getUserId();
            String tempCartKey = CartConstant.CART_IN_REDIS_PREFIX + userInfoTo.getUserKey();
            return stringRedisTemplate.opsForHash().size(cartKey)+stringRedisTemplate.opsForHash().size(tempCartKey);
        }else{
            String tempCartKey = CartConstant.CART_IN_REDIS_PREFIX + userInfoTo.getUserKey();
            return stringRedisTemplate.opsForHash().size(tempCartKey);
        }

    }

    @Override
    public List<CartItemVo> getUserCartItems() throws Exception {
        List<CartItemVo> cartItemVoList = new ArrayList<>();
        //获取当前用户登录的信息
        UserInfoTo userInfoTo = SetCookiesInterceptor.threadLocal.get();
        //如果用户未登录直接返回null
        if (userInfoTo.getUserId() == null) {
            return null;
        } else {
            //获取购物车项
            String cartKey = CartConstant.CART_IN_REDIS_PREFIX + userInfoTo.getUserId();
            //获取所有的
            List<CartItemVo> cartItems = getAllCartItems(cartKey);
            if (cartItems == null) {
                throw new Exception("异常");
            }
            //筛选出选中的
            cartItemVoList = cartItems.stream()
                    .filter(items -> items.getCheck())
                    .map(item -> {
                        //更新为最新的价格（查询数据库）
                        BigDecimal price = productFeignService.getPrice(item.getSkuId()).getData(new TypeReference<BigDecimal>(){}).get();
                        item.setPrice(price);
                        return item;
                    })
                    .collect(Collectors.toList());
        }

        return cartItemVoList;
    }

    private void switchTempCartToRealCart(String cartKey, String tempCartKey, List<CartItemVo> tempCartItems, List<CartItemVo> cartItems) {
        Map<String,String> updateCartItems = new HashMap<String,String>();
        Map<Long, CartItemVo> collect = cartItems.stream().collect(Collectors.toMap(item -> item.getSkuId(), item -> item));
        tempCartItems.forEach(item->{
            CartItemVo cartItemVo = collect.get(item.getSkuId());
            if(cartItemVo!=null){
                cartItemVo.setCount(cartItemVo.getCount()+item.getCount());
                //更新数量
                updateCartItems.put(item.getSkuId().toString(), JSON.toJSONString(cartItemVo));
            }else{
                //新增
                updateCartItems.put(item.getSkuId().toString(), JSON.toJSONString(item));
                cartItems.add(item);
            }
        });
        BoundHashOperations<String, Object, Object> hashOperations = stringRedisTemplate.boundHashOps(cartKey);
        //批量更新
        hashOperations.putAll(updateCartItems);
    }

    public void switchTempCartToRealCart(List<CartItemVo> tempCartItems,String cartKey,String tempCartKey){
        //将临时购物车中的购物项转移到正式购物车中
        List<String> skuIds = tempCartItems.stream().map(item -> item.getSkuId().toString()).collect(Collectors.toList());

    }

    public List<CartItemVo> getAllCartItems(String cartKey){
        List<CartItemVo> cartItemVos = new ArrayList<CartItemVo>();
        BoundHashOperations<String, Object, Object> hashOperations = stringRedisTemplate.boundHashOps(cartKey);
        List<Object> values = hashOperations.values();

        if(!CollectionUtils.isEmpty(values)){
            List<CartItemVo> cartItemVoList = values.stream().map(obj -> {
                CartItemVo cartItemVo = JSON.parseObject((String) obj, CartItemVo.class);
                return cartItemVo;
            }).collect(Collectors.toList());
            return cartItemVoList;
        }
        return cartItemVos;
    }

    public void cleanCart(String cartKey){
        stringRedisTemplate.delete(cartKey);
    }

    public BoundHashOperations<String, Object, Object> getCartOps(){
        UserInfoTo userInfoTo = SetCookiesInterceptor.threadLocal.get();
        String cartKey = CartConstant.CART_IN_REDIS_PREFIX;
        if(userInfoTo.getTempUser()){
            cartKey = cartKey + userInfoTo.getUserKey();
        }else{
            cartKey = cartKey + userInfoTo.getUserId();
        }
        return stringRedisTemplate.boundHashOps(cartKey);
    }
}
